package com.java.code.socket;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

/**
 * BIO:
 * 等待客户端发数据这个过程是阻塞的，这样就造成了一个线程只能处理一个请求的情况，
 * 而机器能支持的最大线程数是有限的，这就是为什么BIO不能支持高并发的原因
 * <p>
 * NIO:
 * 当一个Socket建立好之后，Thread并不会阻塞去接受这个Socket，
 * 而是将这个请求交给Selector，Selector会不断的去遍历所有的Socket
 * 一旦有一个Socket建立完成，他会通知Thread，然后Thread处理完数据再返回给客户端
 */
public class SocketChannelClient {
    private int i = -1;

    public SocketChannelClient() {
    }

    public SocketChannelClient(int i) {
        this.i = i;
    }

    public static void main(String[] args) throws UnsupportedEncodingException {
        for (int i = 0; i < 1; i++) {
            new SocketChannelClient(i).startClient(i);
        }
    }


    public void startClient(int i) {
        SocketChannel socketChannel = null;
        Selector selector = null;

        ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
        ByteBuffer readBuffer = ByteBuffer.allocate(1024);

        try {
            socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);
            socketChannel.connect(new InetSocketAddress("127.0.0.1", 1234));

            selector = Selector.open();
            socketChannel.register(selector, SelectionKey.OP_CONNECT);

            if (socketChannel.finishConnect()) {

                String info = "客户端" + i + ":" + Math.random() * 1000;
                while (true) {
                    System.out.println("-------------------------------------------------------------");
                    writeBuffer.clear();
                    writeBuffer.put(info.getBytes("utf-8"));
                    writeBuffer.flip();

                    while (writeBuffer.hasRemaining()) {
                        socketChannel.write(writeBuffer);

                    }

                    int bytesRead = socketChannel.read(readBuffer);
                    if (bytesRead > 0) {
                        readBuffer.flip();
                        byte[] bytes = new byte[bytesRead];
                        readBuffer.get(bytes, 0, bytesRead);
                        String str = new String(bytes);
                        System.out.println(str);
                        readBuffer.clear();

                    }
                    Thread.sleep(2000);
//                    Thread.sleep(Integer.MAX_VALUE);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            try {
                if (socketChannel != null) {
                    socketChannel.close();
                    System.out.println("关闭socketChannel");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public void hook() {
        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
            @Override
            public void run() {
            }
        }));
    }

}
